/**
 * 
 */
package test.main;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.math3.util.ArithmeticUtils;


/**
 * @author baoyiyang
 *
 */
public class Main {
	
	private static int RANGE = 50;
	private static int SELECT = 5;
	
	private static File output = new File("./output/output.txt");
	
	private static HistoryChecker history = new HistoryChecker("./input/input3.csv");
	
	// most frequent 50, 4, 44, 11, 19, 1, 12, 38, 36, 14, 16, 25, 37
	private static List<Integer> highFrequency = Arrays.asList(50, 4, 44, 19, 38, 11, 23, 37);
	
	// least frequent 47, 33, 13, 12, 9
	private static List<Integer> lowFrequency = Arrays.asList(32, 46);
	private static List<Integer> mustContains = Arrays.asList(50, 4);
	
	private static List<List<Integer>> results = new ArrayList<>();
	private static int draws = 2;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int[] numbers = new int[RANGE];
		for (int i=0; i<RANGE; i++)
			numbers[i] = i+1;
		
		int [] index = new int[SELECT];
		for (int i=0; i<SELECT; i++)
			index[i] = i;
		index[SELECT-1] = SELECT-2;
		
		do {
			next(index);
			int[] result = getNumbers(index, numbers);
			if (valid(result)) {
				List<Integer> row = Arrays.asList(ArrayUtils.toObject(result));
				if (!history.checkMatch(result))
					results.add(row);
			}
		} while (!finished(index));
		
		log(results);
		System.out.println("Shortlist : "+results.size()+" from total possible: "+ArithmeticUtils.binomialCoefficient(RANGE, SELECT)+" ("+(100*results.size()/ArithmeticUtils.binomialCoefficient(RANGE, SELECT))+"%)");
		System.out.println("Match history: "+history.getMatch()+" out of "+history.getSampleSize()+" ("+(100*history.getMatch()/history.getSampleSize())+"%)");
		System.out.println();
		
		Random random = new Random(System.currentTimeMillis());
		for (int i=0; i<draws; i++) {
			int j = random.nextInt(results.size());
			System.out.println("lucky draw: "+j+" - "+results.get(j));
			history.printStats(results.get(j));
		}
		
	}
	
	private static void log(List<List<Integer>> numbers) {
		File parent = output.getParentFile();
		if (!parent.exists() && !parent.mkdirs()) {
			System.out.println("Unable to create file");
		}
		
		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new FileWriter(output));
			
			for (List<Integer> row : numbers) {
				writer.write(row.toString());
				writer.newLine();
			}
			writer.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static boolean finished(int[] index) {
		for (int i=0; i<index.length; i++) {
			if (index[i] != RANGE-SELECT+i)
				return false;
		}
		return true;
	}
	
	private static void next(int[] index){
		next(index, SELECT-1);
	}
	
	private static int next(int[] index, int i) {
		if (index[i] < (RANGE-SELECT+i)) {
			return ++index[i];
		}
		else if (i==0) {
			return index[i];
		} else {
			int left = next(index, i-1);
			index[i] = left+1;
			return index[i];
		}
	}
	
	private static int[] getNumbers(int[] index, int[] values) {
		int[] result = new int[index.length];
		for (int i=0; i<index.length; i++)
			result[i] = values[index[i]];
		return result;
	}
	
	/**
	 * valid if:
	 * 1. has one adjacent number pair which contains high frequency numbers;
	 * AND 2. has one of most frequent numbers: 44, 10, 22, 28, 4
	 * AND 3. doesn't have one of least frequent numbers: 47, 33, 13, 12, 9
	 * 
	 * @param result
	 * @return
	 */
	private static boolean valid(int[] result) {
		int adjacentCount = 0;
		int highFrequent = 0;
		int highFrequentAdjacent = 0;
		int lowFrequent = 0;
		int mustContain = 0;
		boolean isArithmaticProgression = true;
		double[] doubles = new double[result.length];
		for (int i=0; i<result.length; i++) {
			doubles[i] = result[i];
			
			if (i == 0) continue;
			
			if (i > 0 && result[i] == (result[i-1]+1)) {
				adjacentCount++;
				if (highFrequency.contains(result[i]) || highFrequency.contains(result[i-1]))
					highFrequentAdjacent++;
			}
			
			if (highFrequency.contains(result[i]))
				highFrequent++;
			
			if (lowFrequency.contains(result[i]))
				lowFrequent++;
			
			if (mustContains.contains(result[i]))
				mustContain++;
			
			if (i > 1 && (result[i]-result[i-1] != result[i-1]-result[i-1]))
				isArithmaticProgression = false;
		}
		
		return (adjacentCount < 3) &&
//				(adjacentCount > 0) && 
//				(highFrequentAdjacent > 0) &&
				(lowFrequent == 0) && 
				(highFrequent > 0) && 
//				(mustContain > 0) && 
				!isArithmaticProgression && 
				history.checkHistory(doubles);
	}

}
